package pl.edu.mimuw.irs.core.model.design.processing;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import pl.edu.mimuw.irs.core.global.UniqueObject;


/**
 * @author Jakub Rauch
 * Created on: 2009-05-07
 */
public class Resource extends UniqueObject {

	// *** Attributes

	private String name;
	// Set of custom roles that an actor is capable of acting.
	private Map<Role, RoleInstance> rolesInstancesMap;
	// Getters and setters
	public String getName() {
		if (this.name == null) this.name = createNewName();
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	private Map<Role, RoleInstance> getRolesInstancesMap() {
		if (this.rolesInstancesMap == null) this.rolesInstancesMap = new HashMap<Role, RoleInstance>();
		return this.rolesInstancesMap;
	}
	private void setRolesInstancesMap(Map<Role, RoleInstance> rolesInstancesMap) {
		this.rolesInstancesMap = rolesInstancesMap;
	}
	public Collection<RoleInstance> getRolesInstances() {
		return getRolesInstancesMap().values();
	}
	public void addRolesInstances(Set<RoleInstance> rolesInstances) {
		Map<Role, RoleInstance> rolesInstancesMap = getRolesInstancesMap();
		for (RoleInstance roleInstance : rolesInstances) {
			rolesInstancesMap.put(roleInstance.getRole(), roleInstance);
		}
	}
	public void removeRolesInstances(Set<Role> roles) {
		Map<Role, RoleInstance> rolesInstancesMap = getRolesInstancesMap();
		for (Role role : roles) {
			rolesInstancesMap.remove(role);
		}
	}
	public RoleInstance getRoleInstance(Role role) {
		return getRolesInstancesMap().get(role);
	}
	public void addRoleInstance(RoleInstance roleInstance) {
		getRolesInstancesMap().put(roleInstance.getRole(), roleInstance);
	}
	public void removeRoleInstance(Role role) {
		getRolesInstancesMap().remove(role);
	}
	
	// *** Constructors
	
	public Resource(String name, Set<RoleInstance> rolesInstances) {
		setRolesInstancesMap(new HashMap<Role, RoleInstance>());
		addRolesInstances(rolesInstances);
		setName(name);
		setId(getPrefixedNewId(getName() + "_"));
	}
	
	public Resource(Set<RoleInstance> rolesInstances) {
		this(null, rolesInstances);
	}
	
	// *** Methods
	
	private String createNewName() {
		StringBuffer nameBuffer = new StringBuffer();
		nameBuffer.append("Res");
		//if (getRolesInstances().size() > 0) {
		//	nameBuffer.append("[");
			for (RoleInstance instance : getRolesInstances()) {
				nameBuffer.append(instance.toString());
		//		nameBuffer.append(";");
			}
		//	nameBuffer.replace(nameBuffer.lastIndexOf(";"), 
		//			nameBuffer.length(), "]");
		//}
		return nameBuffer.toString();
	}
	
	/**
	 * Actor meets requirement if he is capable of playing every role of this requirement.
	 */
	public boolean meets(Requirement requirement) {
		return getRolesInstances().containsAll(requirement.getRolesInstances());
	}
	
	/**
	 * Works on requirement. Returns time taken - depends on cost of requirement and 
	 * skills of this actor. Assumes this actor meets this requirement.
	 * @param requirement
	 * @return
	 */
	public double work(Requirement requirement) {
		double timeUnits = 0;
		for (RoleInstance roleInstance : requirement.getRolesInstances()) {
			timeUnits = Math.max(timeUnits, 
					getRoleInstance(roleInstance.getRole()).getUnits() /
					roleInstance.getUnits());
		}
		
		return timeUnits;
	}
}
